package Connection;

use strict;
use IO::Socket::INET;
use IO::Select;


my $NO_AGENT;
eval "use LWP::Simple qw(get);";
if ($@) {
  $NO_AGENT = 1;
}
else {
  $NO_AGENT = 0;
} 

use constant DEFAULT_ATHENA_HOST => "localhost";
use constant DEFAULT_ATHENA_PORT => "9000";



sub new {
  # Get the class name
  my $stInvocant = shift(@_);
  my $stClass = ref($stInvocant) || $stInvocant;
  
  # Create the current instance and bless into class
  my $cSelf = { };
  bless($cSelf,$stClass);
  my %hArgs = ( @_ );
  my $stArgs = \%hArgs;
  
  if (exists $stArgs->{host}) {
    $cSelf->{method} = "athena";
    $cSelf->{host} = $stArgs->{host};
    $cSelf->{port} = $stArgs->{port} || DEFAULT_ATHENA_PORT;
    $cSelf->{proto} = getprotobyname('tcp');
    my $skSocket = IO::Socket::INET->new(PeerAddr=>$cSelf->{host},
					 PeerPort=>$cSelf->{port},
					 Proto=>'tcp',
					 Type=>SOCK_STREAM,
				      );
    $cSelf->{socket} = $skSocket;
    if (defined ($skSocket)) {
      $cSelf->{select} = IO::Select->new($cSelf->{socket});
    }
    else {
      $cSelf->{socket} = undef;
      $cSelf->{select} = undef;
      
      $cSelf->{error} = $!;
    }
  }
  elsif (exists $stArgs->{'url'}) {
    if ($NO_AGENT) {
      die "athena.pl: http method requires perl libwww package.";
    }
    $cSelf->{method} = "http";
    $cSelf->{url} = $stArgs->{'url'};
  }
  else {
    undef $cSelf;
  }
  return $cSelf;
}

sub connect {
  my $cSelf = shift(@_);
  my $rv = 1;
  if (defined $cSelf->{url}) {
    # do nothing ? check http maybe ?
  }
  else {
    $rv = scalar($cSelf->{socket});
    #$rv = $cSelf->{socket}->connect();
  }
  return $rv;
}

sub disconnect {
  my $cSelf = shift(@_);
  my $rv = 1;
  if (defined $cSelf->{url}) {
    # do nothing ? check http maybe ?
  }
  elsif (defined ($cSelf->{socket})) {
    $cSelf->{socket}->send("quit");
    $rv = $cSelf->{socket}->close();
  }
  return $rv;
}

sub send {
  my $cSelf = shift(@_);
  my $bytes = shift(@_);
  my $rv = 1;
  #return $cSelf->{socket}->print($bytes . "\r\n");
  if (defined $cSelf->{url}) {
    # do nothing ? check http maybe ?
  }
  else {
    my $flags = pack('i', hex(0x8));
    $rv = $cSelf->{socket}->send($bytes . "\r\n", $flags);
  }
  return $rv;
}

sub recv {
  my $cSelf = shift(@_);
  my $rv;
  my $flags = "0";
  my $stBuild;
  my $stHolder;
  my $stEOR = "";
  my $boCont = 1;
  my $iWantLen = 16384;
  my $iGetLen = 0;

  if (defined $cSelf->{url}) {
    # do nothing ? check http maybe ?
    $rv = 1;
  } else {
    $rv = $cSelf->{socket}->recv($stHolder, $iWantLen, $flags);
    if (defined($rv)) {
      if ($stHolder =~ /^Content-Length: /) {
	my $stHeader = substr($stHolder, 0, index($stHolder, "\n"));
	my ($stHname, $stHval) = split(" ", $stHeader);
	$iWantLen = $stHval;
	$stHolder = substr($stHolder, index($stHolder, "\n"));
	if ($stHolder) {
	  $stBuild .= $stHolder;
	}
	while ($boCont) {
	  $iGetLen = $iWantLen;
	  $rv = $cSelf->{socket}->recv($stHolder, $iGetLen, $flags);
	  $iWantLen -= $iGetLen;
	  $stEOR = substr($stHolder, -2, 2);
	  $stBuild .= $stHolder;
	  if ($stEOR eq "\r\n") {
	    $boCont = 0;
	  }
	  $rv = $stBuild;
	}
      } 
      else {
	$rv = 1;
      }
    } 
    else {
      $rv = undef;
    }
  }
  return $rv;
}

sub httpGet {
  my $cSelf = shift(@_);
  my $stUrl = shift(@_);
  my $stResult = undef;
  if (! $NO_AGENT) {
    $stResult = get($stUrl);
  }
  return $stResult;
}

sub getMethod {
  my $cSelf = shift(@_);
  return $cSelf->{method};
}

sub getHost {
  my $cSelf = shift(@_);
  return $cSelf->{host};
}

sub getPort {
  my $cSelf = shift(@_);
  return $cSelf->{port};
}

sub getUrl {
  my $cSelf = shift(@_);
  return $cSelf->{url};
}

1;
